package com.cl.service;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.cl.dao.SearchDao;
import com.cl.dto.ObjectDTO;
import com.cl.entity.BasePayfactor;
import com.cl.entity.CcPay;
import com.cl.entity.UWhite;
import com.cl.entity.common.DBObject;
import com.cl.util.ClassNameReplaceUtil;
import com.cl.util.ExpressionUtil;
import com.fasterxml.jackson.databind.util.ClassUtil;

@Service
public class PayCaculateService {
	
	private final static String defaultPay = "0";
	
	//c4w 缓存稿酬因子及白名单
	private HashMap<String,List<BasePayfactor>> map_list_basePayfactor;
	private HashMap<String,UWhite> map_white= new HashMap<String,UWhite>();
	
	@Autowired
	private SearchDao searchDao;
	
    @Value("#{classmappingProperties}")
    private HashMap<String, String> classMapping;
    
    @Autowired
    private ExpressionUtil expressionUtil;

   
    //c4w 加载缓存
	@PostConstruct  
    public void  init(){  
		map_list_basePayfactor = new HashMap<String,List<BasePayfactor>>();
		resetWhiteMap();
		System.out.println("******同步成功一条 test*** syncId = ");
    }  	
    
	public void resetBasePayfactor(){
		map_list_basePayfactor.clear();
	}
	public void resetWhiteMap(){
		//清除之前脏缓存
		map_white.clear();
		List <UWhite> ls = searchDao.getEntityList(UWhite.class);
		for(UWhite w:ls){
			map_white.put(getWhiteKey(w),w);
		}
	}
	public boolean isWhite(CcPay p){
		//考虑到在稿酬计算的周期（半年内）,人员的组织机构调整，所以只匹配姓名
		String aid = p.getAuthorId();
		if(aid==null)
			return false;
		int pos = aid.lastIndexOf("[");
		if(pos!=-1)
			aid = aid.substring(0,pos);
		String key = p.getWorkitem()+"."+aid;
		if(map_white.get(key)!=null)
			return true;
		else
			return false;
	}
	
	
	private String getWhiteKey(UWhite w){
		return w.getWorkitem()+"."+w.getAuthorId();
	}
 
    /**
     * 获得旧版本中与新版本的类名对应的映射
     *
     * @param entity
     * @return
     */
    public String getNewClassName(String oldclass) {
        return classMapping.get(oldclass);
    }
	
	public List<BasePayfactor> getPayfactorList(CcPay cp){
		//0215
		//cp.setClass_(ClassNameReplaceUtil.replaceName1(cp.getClass_()));
		String type1=cp.getClass_();
		String type = ClassNameReplaceUtil.replaceName1(cp.getClass_());
		
		//String type = cp.getClass_();
		//c4w 加入缓存机制,不改动之前逻辑
		List<BasePayfactor> ls= map_list_basePayfactor.get(type);
		//0216
		List<BasePayfactor> ls1= map_list_basePayfactor.get(type1);
		
		if(ls==null&&ls1==null){
			ls = searchDao.getPayfactorListByType(type);
			map_list_basePayfactor.put(type, ls);
		}
		return ls;
	}
	
	
	/**
	 * 初步判断basepayfactor是否匹配
	 * @param bpf
	 * @param cp
	 * @return
	 */
	public boolean excuteExpress(BasePayfactor bpf,CcPay cp){
//		/cp.setClass_(ClassNameReplaceUtil.replaceName1(cp.getClass_()));
		if(StringUtils.equals(bpf.getType(),ClassNameReplaceUtil.replaceName1(cp.getClass_()))){
			//
//			cp.setClass_(ClassNameReplaceUtil.replaceName1(cp.getClass_()));
			return true;
		}else if(StringUtils.isEmpty(bpf.getType())){
			return true;
		}else if(StringUtils.equals(bpf.getType(), "0")){
			return true;
		}else{
			return false;
		}
	}

	public String getPayValue(CcPay pay, ObjectDTO objDTO) throws Exception{
		//c4w 每条稿酬都从数据库加载，性能较低，稿酬因子业务上不会轻易调整的，建议加载一次稿酬因子，重复利用
		//List<BasePayfactor> list = searchDao.getPayfactorListByType(pay.getClass_());
		//
// 		pay.setClass_(ClassNameReplaceUtil.replaceName1(pay.getClass_()));
		
		if(isWhite(pay)){
			pay.setPayFactorNotes("因为用户"+pay.getAuthorId()+" 在白（干）名单中，置稿酬为0");
			return "0";
		}
		//
		//pay.setClass_(ClassNameReplaceUtil.replaceName1(pay.getClass_()));
		List<BasePayfactor> list  = getPayfactorList(pay);
		//
		//pay.setClass_(ClassNameReplaceUtil.replaceName1(pay.getClass_()));
		return getPayValue(pay, list, objDTO);
	}
	
	private String getPayValue(CcPay pay, List<BasePayfactor> list, ObjectDTO objDTO) throws Exception{
		String result = defaultPay;
		boolean hasBasefactor = false;
//		//0215
//		String cp=ClassNameReplaceUtil.replaceName1(pay.getClass_());
//		pay.setClass_(cp);
		//
		
		//遍历payfactor获取匹配的稿酬因子
		for(int i=0; i<list.size(); i++)
		{
			BasePayfactor factor = list.get(i);
		//	System.out.println("pppppppppppppppppppppppppppppppp0216333:"+factor.getExpressions()+factor.getNotes());
			//
			//String c=ClassNameReplaceUtil.replaceName1(pay.getClass_());
			//pay.setClass_(ClassNameReplaceUtil.replaceName1(pay.getClass_()));
			if(!excuteExpress(factor,pay)){
				continue;
			}
			String expresion = factor.getExpressions();
			//
			pay.setClass_(ClassNameReplaceUtil.replaceName1(pay.getClass_()));
			try {
				//0215
//				pay.setClass_(ClassNameReplaceUtil.replaceName1(pay.getClass_()));
				
				boolean isMatch = expressionUtil.excute(expresion, pay, objDTO.objClass, objDTO.obj);
				if(isMatch){
					hasBasefactor = true;
					if(StringUtils.indexOf(factor.getPayFactor(),"/")>=0){
						String[] baseGcFactory = StringUtils.split(factor.getPayFactor(),"/");
						Double dn = Double.valueOf(ObjectUtils.toString(pay.getDocNumber()));
						Double base =  Double.valueOf(baseGcFactory[1]);
						Double factory = dn/base;
						DecimalFormat   myformat=new   java.text.DecimalFormat("#0");
						result = String.valueOf(
							    myformat.format(factory*Integer.parseInt(baseGcFactory[0]))
							  );
					}else{
						result = String.valueOf(factor.getPayFactor());
					}
					pay.setPayFactorNotes(factor.getNotes()+"\r\n注:本次稿酬计算依据\"稿酬因子\"中编号["+factor.getId()+"]的规则生成.");
					break;
				}
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				throw new Exception(e.getMessage()+"\r\n稿酬表达式执行错误:\r\n"+expresion+"    ;第"+factor.getId()+"号，表达式异常!涉及对象："+objDTO.objClass+" "+pay.getKeyval());
			}
			
		}
		
		if(!hasBasefactor)
			pay.setPayFactorNotes("没有相匹配的稿酬因子,请完善稿酬因子后确认!");
		return result;	 
		
		
	}
	
}
